/* This is a test bed program to test the connectionmanager class.
 *
 */
package org.kth.dks.test_bed;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.StringTokenizer;
import java.util.Vector;

import org.kth.dks.dks_comm.ConnectionManager;
import org.kth.dks.dks_comm.DKSRef;
import org.kth.dks.dks_comm.Message;
import org.kth.dks.util.DKSPrintTypes;

public class TestBed {
  long sendCounter = 0;
  long sendDroped = 0;

    public static void main(String[] args) {
      if (args.length < 2) {
	  System.err.println("Parameter: DKS_ID(int) port_number(int)");
	  System.exit(0);
      }

    TestBed myTestBed = new TestBed();
    myTestBed.doTest(Integer.parseInt(args[0]), Integer.parseInt(args[1]));
  }

  void doTest(int myid, int myport) {
    RoutingTable rt = new RoutingTable();

    String myip = null;

    try {
      myip = InetAddress.getLocalHost().getHostAddress();
    }
    catch (UnknownHostException uhexp) {
      uhexp.printStackTrace();
      System.exit(0);
    }

    System.out.println("DKS Communication layer testbed.");
    System.out.println("DKS ID: " + myid + "   Port: " + myport + "  IP: " +
                       myip);

      DKSRef me = null;
    ConnectionManager cm = null;
    try {
      me = DKSRef.newDKSRef("dks://"+myip+":"+myport+"/0/"+myid+"/0");
      cm = ConnectionManager.newInstance(myport); // Static factory only used for testing, should use getInstance (singleton)
    } catch (IOException ex) { ex.printStackTrace(); return; }

    //ReadMessages RM = new ReadMessages(CM);

    String command = null, input = null;

    while (true) {
      command = null;
      System.out.println("Command:>> ");
      input = getInput();
      StringTokenizer st = new StringTokenizer(input);
      if (st.hasMoreTokens()) {
        command = st.nextToken();

      }
      if (command == null) {
    	  System.out.println("Invalid command. Try again please.");
      }
      else if (command.equalsIgnoreCase("EXIT")) {
        System.exit(0);
      }
      else if (command.equalsIgnoreCase("SEND")) {
        //SEND id msg
        if (st.countTokens() == 2) {
          int id = Integer.parseInt(st.nextToken());
          DKSRef node = rt.getDKSRef(id);
          Message msg = new Message(st.nextToken().getBytes(), id);
          //cm.send(node, msg);
        }
      }
      else if (command.equalsIgnoreCase("AUTO")) {
        //AUTO id1...idn
        if (st.countTokens() > 0) {
          Vector nodes = new Vector();
          while (st.hasMoreTokens()) {
            int id = Integer.parseInt(st.nextToken());
            DKSRef node = rt.getDKSRef(id);
            if (node != null) {
              nodes.addElement(node);
            }
          }
          autoSend(cm, nodes);
        }
      }
      else if (command.equalsIgnoreCase("SIM")) {
        //SIM
        simulate(myip);
      }
      else if (command.equalsIgnoreCase("SIMP")) {
        //SIMP
    	  System.out.println("Sent: " + sendCounter + "  sent but droped: " +
                           sendDroped);
      }
    }
  }

  private void simulate(String ip) {
    int number = 2;
    int msgs = 1000;
    java.util.Random rand = new java.util.Random( (new java.util.Date()).
                                                 getTime());

    int port = 5555;
    int id = 0;

    DKSRef dksRefs[] = new DKSRef[number];
    ConnectionManager cms[] = new ConnectionManager[number];
    Simulator_Node sns[] = new Simulator_Node[number];

    for (int i = 0; i < number; i++) {
      try {
        dksRefs[i] = DKSRef.newDKSRef("dks://" + ip + ":" + port + i + "/0/" +
                                      id + i + "/0");
      }catch (Exception ex) { ex.printStackTrace(); }

      //cms[i] = new ConnectionManager(dksRefs[i]);
      sns[i] = new Simulator_Node(cms[i]);
    }

    int s, r;
    sendCounter = 0;
    sendDroped = 0;

    for (int i = 0; i < msgs; i++) {
      s = rand.nextInt(number);
      r = rand.nextInt(number);
    Message message = new Message("SIMULATOR".getBytes(), (int)dksRefs[r].getID());
      //if (cms[s].send(dksRefs[r], message)) {
        //sendCounter++;
      //}
      //else {
        //sendDroped++;
      //}
    }
  }

  private void autoSend(ConnectionManager CM, Vector nodes) {
    String data = "fhdsfhiotyiojwoqpewsalakdnvmcnvkncdsihfdlfh";
    for (int i = 0; i < 10; i++) {
      data = data + data;
    }

    for (int i = 0; i < 200; i++) {
      for (int j = 0; j < nodes.size(); j++) {
        Message msg = new Message(data.getBytes(), (int)((DKSRef)nodes.elementAt(j)).getID());
        //if (!CM.send( (DKSRef) nodes.elementAt(j), msg)) {
	  //  DKSPrint.println(DKSPrintTypes.TEST_BED, "Output buffer is full.");
          //return;
        //}
      }
    }
  }

  private String getInput() {
    InputStreamReader isr = new InputStreamReader(System.in);
    BufferedReader br = new BufferedReader(isr);
    String input = null;

    try {
      input = br.readLine();
    }
    catch (Exception ex) {
      ex.printStackTrace();
      input = null;
    }
    return input;
  } //GetInput
}//TestBed class




/* A thread to read incomming messages
 *
 */
class ReadMessages
    extends Thread {
  private ConnectionManager cm = null;

  ReadMessages(ConnectionManager newcm) {
    this.cm = newcm;
    this.start();
    this.setName(ReadMessages.class.getName());
  }

  public void run() {
    while (true) {
//      CommBufferInElement buff = cm.receive();  // buffers removed
//      DKSPrint.println(DKSPrintTypes.TEST_BED,"");
//      DKSPrint.println(DKSPrintTypes.TEST_BED, "New MSG from DKS node " + buff.getDKSRef().getID() +
//                         ",MSG: " + new String(buff.getMsg().getData()));
      //DKSPrint.Println( "New MSG from DKS node " + buff.GetDKSRef().GetID() );
//      DKSPrint.print(DKSPrintTypes.TEST_BED, "Command:>> ");
    }
  }
}//ReadMessages class
